#ifndef __FILE_SERVER_H__
#define __FILE_SERVER_H__

#include "lib/signals/SIGTERM_Handler.h"
#include "lib/signals/SIGPIPE_Handler.h"

#include "lib/Fifo.h"
#include <string>
#include <list>

/**
 *
 * A FileServer handles the file transfers and download requests
 *
 */

class FileServer {

private:


	SIGTERM_Handler sigTerm;	//interruption signal
	SIGPIPE_Handler sigPipe;	//pipe error signal

	int myUserID;

	std::list<int> children;

	/**
	 * Requests the file to the user
	 *
	 * Returns true if the download has been accepted
	 *
	 * -- This is a blocking function
	 *
	 */
	bool requestDownload(std::string &fileName, int userID);

	/**
	 * Send the file data
	 *
	 * -- This is a blocking function
	 *
	 */
	virtual bool sendFile(Fifo &fileTransfer, std::string & fileName);

	/**
	 * Download the file data
	 *
	 * -- This is a blocking function
	 *
	 */
	virtual bool receiveFile(Fifo &fileTransfer,std::string & fileName);

	/**
	 * -- This is a blocking function
	 * Process the file request from the user
	 */
	void processRequest(int userID, std::string &file);


	/**
	 * --This is a blocking function
	 * wait until a user submits a request and process it
	 *
	 * returns false if request failed
	 *
	 */
	bool listenToRequests(Fifo &requests);


	/**
	 * wait until every child process finishes sending the file
	 */
	void finishSendingFiles();

public:

	/**
	 * userID: id of the user sharing the files
	 */
	FileServer(int userID);

	virtual ~FileServer();

	/*
	 * Download the file from the user.
	 *
	 * Returns true if the download is successful.
	 * Returns false if the download is cancelled or encounters a problem.
	 *
	 * PreCondition: the user must be online and the file has to be shared
	 *
	 * */

	bool downloadFile(std::string &fileName, int userID);

	/**
	 * Start the server and listen to incoming file requests from other users
	 *
	 * Stop the server either by calling stopServer or by sending SIGINT
	 *
	 */
	void startServer();

	/**
	 * Stop listening to requests
	 */
	void stopServer(int serverPid);

	/**
	 * Returns true if the server is running
	 */
	bool isRunning();

	int getUserID() {
		return myUserID;
	}

};

#endif /* __FILE_SERVER_H__ */
